//
// PeopleTab.cs
// 
// Defines the tab responsible for handling Actors and Directors.
//
// Author:
//   Radu Tofoleanu <kenjiru.ro@gmail.com>
//
// Copyright (C) 2007-2008 Radu Tofoleanu (http://kenjiru.ro)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.IO;
using System.Data;
using System.Xml.Serialization;
using Gtk;
using Gdk;
using EigaLib;

namespace EigaApp
{
	public partial class PeopleTab : Gtk.Bin
	{
		// lucrul cu baza de date
		private EigaDb eigaDb = null;

		private bool personAdd = false;
		private bool personEdit = false;
		private TreeIter personIter;
		TreeIter actorsIter;
		TreeIter directorsIter;
		
		public EigaDb DbConn
		{
			set {
				eigaDb = value;
			}
		}
		
		public PeopleTab()
		{
			Build();
			
			peopleList.AppendColumn ("People", new CellRendererText (), "text", 1);
			peopleList.Model = new TreeStore (typeof(int), typeof (string));
			
			castList.Model = new ListStore (typeof (string), typeof (string));
			castList.AppendColumn ("Movie", new CellRendererText (), "text", 0);
			castList.AppendColumn ("Role", new CellRendererText (), "text", 1);
			
			personCountry.Model = new ListStore (typeof (int), typeof (string));
			
			CellRendererText rnd = new CellRendererText ();
			personCountry.PackStart (rnd, true);
			personCountry.SetAttributes (rnd, "text", 1);
		}
		
		private void Message(string msg)
		{
			Gtk.MessageDialog msgDlg = new Gtk.MessageDialog(null, 
				DialogFlags.Modal,
				MessageType.Info,
				ButtonsType.Close, 
				msg);
			msgDlg.Run ();
			msgDlg.Destroy ();
		}
		
		private void PeopleBeginEdit()
		{
			if (personEdit && personIter.Stamp == 0) {
				personEdit = false;
				return;
			}
			
			peopleEdit.Sensitive = false;
			peopleSave.Sensitive = true;
			peopleCancel.Sensitive = true;
			
			personName.IsEditable = true;
			personBirthday.IsEditable = true;
			personCountry.Sensitive = true;
			personFunction.Sensitive = true;
		}
		
		private void PeopleEndEdit()
		{
			peopleEdit.Sensitive = true;
			peopleSave.Sensitive = false;
			peopleCancel.Sensitive = false;
			
			personName.IsEditable = false;
			personBirthday.IsEditable = false;
			personCountry.Sensitive = false;
			personFunction.Sensitive = false;
			
			if (personAdd == true) {
				peopleAdd.Sensitive = true;
				personAdd = false;
			}
			
			if (personEdit == false) {
				personEdit = false;
			}
		}
		
		private void PeopleCancelEdit()
		{
			PeopleClear ();
		}
		
		private void PeopleClear ()
		{
			personName.Text = "";
			personBirthday.Text = "";
			personCountry.Active = -1;
			personFunction.Active = -1;
			
			ListStore personModel = (ListStore) personCountry.Model;
			ListStore castStore = (ListStore) castList.Model;
			
			personModel.Clear();
			castStore.Clear();
			
			personPicture.Pixbuf = Gdk.Pixbuf.LoadFromResource("no_photo.jpg");
		}
		
		public void Refresh()
		{
			PeopleClear();
			
			if (eigaDb.IsConnected() == false) {
				Console.WriteLine ("PeopleTab: Refresh(): nu exista conexiune la baza de date!");
				return;
			}
			
			peopleList.Model = eigaDb.GetAllPeople();
			personCountry.Model = eigaDb.GetAllCountries();
			
			peopleList.Model.GetIter (out actorsIter, new TreePath ("0"));
			peopleList.Model.GetIter (out directorsIter, new TreePath ("1"));
			
			peopleList.ExpandAll();
		}
		
		private void PeopleSaveEdit()
		{
			int id = (int) peopleList.Model.GetValue (personIter, 0);
			string name = personName.Text;
			string birthday = personBirthday.Text;
			int function = personFunction.Active;
			int countryID = -1;
			
			TreeIter cIter;
			if (personCountry.GetActiveIter (out cIter) == true) {
				countryID = (int) personCountry.Model.GetValue (cIter, 0);
			}

			// testez daca datele sunt valide, adica nenule
			if(name == "" || birthday == "" || function == -1 || countryID == -1) {
				Message ("Trebuie sa completati toate campurile!");
				return;
			}
			
			byte[] buff = personPicture.Pixbuf.SaveToBuffer ("jpeg");
						
			// !!
			if (! eigaDb.EditPerson (id, name, birthday, countryID, function, buff)) {
				Message ("Nu am putut salva modificarile!");
				PeopleCancelEdit();
				PeopleEndEdit();
				return;
			}
			
			PeopleEndEdit();
			
			// verificam daca s-a modificat functia persoanei (actor/director)
			
			TreeStore store = (TreeStore) peopleList.Model;
			store.SetValue (personIter, 1, name);

			TreeIter parentIter;
			store.IterParent (out parentIter, personIter);
			
			if (parentIter.GetHashCode () == actorsIter.GetHashCode () && function == 1) {
				store.Remove (ref personIter);
				TreeIter newIter = store.AppendValues (directorsIter, id, name);
				TreePath newPath = store.GetPath (newIter);
				TreeViewColumn newColumn = peopleList.GetColumn (0);
				peopleList.SetCursor (newPath, newColumn, false);
				return;
			} 
			if (parentIter.GetHashCode () == directorsIter.GetHashCode () && function == 0) {
				store.Remove (ref personIter);
				TreeIter newIter = store.AppendValues (actorsIter, id, name);
				TreePath newPath = store.GetPath (newIter);
				TreeViewColumn newColumn = peopleList.GetColumn (0);
				peopleList.SetCursor (newPath, newColumn, false);
			}
		}
		
		private void PeopleSaveAdd()
		{
			int id;
			string name = personName.Text;
			string birthday = personBirthday.Text;
			int function = personFunction.Active;
			int countryID = 0;
			
			TreeIter cIter;
			if (personCountry.GetActiveIter (out cIter) == true) {
				countryID = (int) personCountry.Model.GetValue (cIter, 0);
			}
			
			byte[] buff = personPicture.Pixbuf.SaveToBuffer ("jpeg");
			
			if (! eigaDb.AddPerson (out id, name, birthday, countryID, function, buff)) {
				PeopleCancelEdit();
				PeopleEndEdit();
				Message ("Nu am putut salva noua inregistrare!");
				return;
			}
			
			PeopleEndEdit();
				
			TreeStore model = (TreeStore) peopleList.Model;
			if(function == 0) {
				model.AppendValues(actorsIter, id, name);
			} else {
				model.AppendValues(directorsIter, id, name);
			}
		}
		
		////////////////////////////////////////////////////////////////////////
		// Events
		////////////////////////////////////////////////////////////////////////
		
		protected virtual void OnPeopleListRowActivated(object o, Gtk.RowActivatedArgs args)
		{
			if (eigaDb.IsConnected() == false) {
				Message ("Nu sunteti conectat la baza de date!");
				return;
			}
				
			TreeView tr = o as TreeView;
			TreePath path = args.Path;
			TreeIter pIter;
			
			tr.Model.GetIter (out pIter, path);
			int personID = (int) tr.Model.GetValue (pIter, 0);
			
			if (personID < 0) {
				return;
			}
			
			string name, birthday;
			int functionID, countryID;
			byte[] buff;
			
			if (! eigaDb.GetPerson (personID, out name, out functionID, out birthday, 
			                      out countryID, out buff)) {
				return;
			}
			
			personName.Text = name;
			personFunction.Active = functionID;
			personBirthday.Text = birthday;
			personCountry.Active = countryID;
			
			if (buff == null || buff.Length == 0 ) {
				personPicture.Pixbuf = Gdk.Pixbuf.LoadFromResource("no_photo.jpg");
			} else {
				personPicture.Pixbuf = new Pixbuf (buff);
			}
					
			// selectez tara corespunzatoare
			if (countryID>0) {
				ListStore store = (ListStore) personCountry.Model;
				TreeIter iter;
				if (store.GetIterFirst (out iter)) {
					do {
						int id = (int)store.GetValue (iter, 0);

						if (id == countryID) {
							personCountry.SetActiveIter(iter);
							break;
						}
					} while (store.IterNext (ref iter));
				}
			}
			
			if (functionID == 0) {
				// actor
				castList.Columns[1].Visible = true;
			} else {
				castList.Columns[1].Visible = false;
			}
			
			castList.Model = eigaDb.GetCastPerson (functionID, personID);
			
			personIter = pIter;
		}

		protected virtual void OnPeopleEditClicked(object sender, System.EventArgs e)
		{
			if (eigaDb.IsConnected() == false) {
				Message ("Nu sunteti conectat la baza de date!");
				return;
			}
			
			personEdit = true;
			PeopleBeginEdit ();
		}

		protected virtual void OnPeopleCancelClicked(object sender, System.EventArgs e)
		{
			PeopleCancelEdit ();
			PeopleEndEdit ();
		}

		protected virtual void OnPeopleSaveClicked(object sender, System.EventArgs e)
		{
			if (eigaDb.IsConnected() == false || (personEdit && personIter.Stamp == 0)) {
				if (eigaDb.IsConnected() == false)
					Message ("Nu sunteti conectat la baza de date!");
				
				PeopleCancelEdit ();
				PeopleEndEdit ();
				return;
			}
			
			if (personAdd == true) {
				PeopleSaveAdd ();
			} else {
				PeopleSaveEdit ();
			}
		}

		protected virtual void OnPeopleAddClicked(object sender, System.EventArgs e)
		{
			if (eigaDb.IsConnected() == false) {
				Message ("Nu sunteti conectat la baza de date!");
				return;
			}
			
			personAdd = true;
			
			PeopleBeginEdit();
			PeopleClear ();
			peopleAdd.Sensitive = false;
		}

		protected virtual void OnImgButtonClicked(object sender, System.EventArgs e)
		{
			if (personAdd == false && personEdit == false)
				return;
				
			FileFilter filter = new FileFilter ();
			filter.Name = "jpeg";
			filter.AddPattern ("*.jpeg");
			filter.AddPattern ("*.jpg");
			
			FileChooserDialog fc = new FileChooserDialog ("Alege o imagine",
				null,
				FileChooserAction.Open,
				"Cancel", ResponseType.Cancel,
				"Open", ResponseType.Accept);
			fc.Filter = filter;

			if (fc.Run () == (int) ResponseType.Accept) {
				byte[] buff = new byte[1000];
				int read;
				
				FileStream file = File.Open (fc.Filename, FileMode.Open);
				MemoryStream mem = new MemoryStream ();
				while ((read = file.Read (buff, 0, buff.Length)) > 0) {
					mem.Write (buff, 0, read);
				}
				file.Close();
				
				Pixbuf pixbuf = new Pixbuf (mem.ToArray ());
				personPicture.Pixbuf = pixbuf;
          }
          fc.Destroy();
          // am adaugat un comentariu
		}

		protected virtual void OnPeopleDeleteClicked(object sender, System.EventArgs e)
		{
			if (eigaDb.IsConnected() == false) {
				Message ("Nu sunteti conectat la baza de date!");
				return;
			}
			
			TreePath path;
			TreeIter iter;
			TreeViewColumn col;
			TreeStore peopleStore = (TreeStore) peopleList.Model;
			
			peopleList.GetCursor (out path, out col);
			if (! peopleStore.GetIter (out iter, path)) {
				Message ("Pentru a sterge o persoana, trebuie mai intai sa o selectati!");
				return;
			}
			
			int personID = (int) peopleList.Model.GetValue(iter, 0);
			
			if (personID < 0)
				return;
			
			if (!eigaDb.DeletePerson (personID)) {
				Message ("Nu am putut sterge inregistrare!");
				return;
			}
			
			PeopleClear ();

			if (personIter.Stamp == iter.Stamp)
				personIter.Stamp = 0;
			peopleStore.Remove (ref iter);
		}
	}
}
